"""
什么是用户的复购周期
在这里我们结合一个电商销售数据来感受下shift函数的使用。我们有一份客户和购买时间的数据，现在想统计每位用户在今年的平均复购周期和全部用户的平均复购周期。

每位用户的平均复购周期：每两个复购时间之间的天数之和 / 用户总复购次数
全部用户的平均复购周期：全部用户的平均复购周期之和 / 总复购用户数

通过例子进行说明

    姓名      时间
    张三     2021/1/1
    张三     2021/1/7
    张三     2021/1/10
    张三     2021/1/20
    张三     2021/1/28

张三用户的复购间隔分别为：6（ 1号 和 7号 的间隔），3（7号和10号），10，8；
也就是相邻两次购买时间之间的间隔。

那么张三的平均复购周期：（6 + 3 + 10 + 8）/ 4 = 6.75
"""
"""
统计次数
筛选出复购用户，即次数大于1的
按照 姓名和购买时间 升序排列
求出复购时间间隔
统计每个复购用户的复购总天数和总次数
求出每位用户平均复购周期
"""
import pandas as pd
from faker import Faker

fake = Faker(locale="zh_cn")

df = pd.DataFrame(
    data={
        "姓名": [fake.name() for _ in range(20000)],
        "时间": [fake.date_between(start_date="-60d", end_date="today") for _ in range(20000)]
    }
)

# 统计次数
df1 = df.groupby("姓名").count().sort_values(by="时间", ascending=False).reset_index().rename(columns={"时间": "次数"})
# print(df1)

# 筛选出复购用户
df1 = df1.loc[df1["次数"] > 1, :]
# print(df1)

# 从原始数据中取出用户复购数据
df2 = df.loc[df["姓名"].isin(df1["姓名"].tolist())]
# print(df2)

# 按照购买时间升序排列
df2 = df2.sort_values(by=["姓名", "时间"], ascending=[True, True]).reset_index(drop=True)
# print(df2)

# 根据每位复购用户的数据移动一个单位
# 在行方向上移动一个单位：
df2 = df2.assign(时间1=lambda x: x.groupby("姓名").shift())
# print(df2)

# 将NaN数据删除
df2 = df2.loc[~pd.isna(df2["时间1"]), :]
# print(df2)

# 求出复购时间间隔
# 两个字段：时间和时间1的差值，就是每位用户的复购时间间隔，可能存在多个
df2 = df2.assign(间隔=lambda x: x["时间"] - x["时间1"])
df2 = df2.assign(天=df2["间隔"].apply(lambda x: x.days))
print(df2)

# 统计每个复购用户的复购总天数和总次数
df2 = df2.groupby("姓名").agg({"天": "sum", "间隔": "count"}).reset_index().rename(columns={"间隔": "复购次数"})
# print(df2)

# 求出每位用户平均复购周期
df2 = df2.assign(平均复购周期=lambda x: x["天"] / x["复购次数"])
print(df2)